package com.gitee.cui.netty.bytebuf;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import org.junit.Test;

import static com.gitee.cui.netty.bytebuf.PrintAttribute.print;

/**
 * 缓冲区切片测试类
 * @author cuiqingqiang
 * @version 1.0
 * @date 2021/10/22 14:33
 **/
public class ByteBufSliceTest {

    @Test
    public void byteBufSliceTest() {
        ByteBuf buffer = ByteBufAllocator.DEFAULT.buffer(9, 100);
        print("动作：分配ByteBuf(9,100)", buffer);
        buffer.writeBytes(new byte[] {1, 2, 3, 4});
        print("动作：写入4个字节（1，2，3，4）", buffer);
        /**
         * 调用slice()方法后，返回的切片是一个新的ByteBuf对象，该对象的几个重要属性值大致如下：
         * readerIndex（读指针）值为0。
         * writerIndex（写指针）值为源ByteBuf的readableBytes()可读字节数。
         * maxCapacity（最大容量）值为源ByteBuf的readableBytes()可读字节数。
         * 切片后的新ByteBuf有两个特点：切片不可以写入，
         * 原因是：maxCapacity与writerIndex值相同。
         * 切片和源ByteBuf的可读字节数相同，原因是：切片后的可读字节数为自己的属性writerIndex – readerIndex，也就是源ByteBuf的readableBytes() - 0。
         * 切片后的新ByteBuf和源ByteBuf的关联性如下：切片不会复制源ByteBuf的底层数据，底层数组和源ByteBuf的底层数组是同一个。
         * 切片不会改变源ByteBuf的引用计数。从根本上说，slice()无参数方法所生成的切片就是源ByteBuf可读部分的浅层复制。
         */
        ByteBuf byteBuf = buffer.slice();
        print("动作：切片 slice", byteBuf);
        /**
         * 和slice切片不同，duplicate()方法返回的是源ByteBuf的整个对象的一个浅层复制，包括如下内容：
         * Duplicate()的读写指针、最大容量值，与源ByteBuf的读写指针相同。
         * duplicate()不会改变源ByteBuf的引用计数。
         * duplicate()不会复制源ByteBuf的底层数据。
         * duplicate()和slice()方法都是浅层复制。
         * 不同的是，slice()方法是切取一段的浅层复制，而duplicate()是整体的浅层复制。
         */
        ByteBuf duplicate = buffer.duplicate();
        print("动作：切片 duplicate", duplicate);
    }
}
